"""
@File    :   request_validation_data_convert.py
@Time    :   2024/03/11 10:20:40
@Author  :   Qrj
@Email   :   923207736@qq.com
@description   :   fastapi的pydantic验证失败信息转换工具(Query、Path、Form等都适用)
"""

from fastapi.exceptions import RequestValidationError

from src.typings import RequestValidationErrorConvertedDataT

# 自定义pydantic验证失败的错误信息字典(key为type, value为msg)
PydanticValidateErrorMessagesDict = {
    "string_too_long": "最多包含{max_length}个字符",
    "string_too_short": "应至少包含{min_length}个字符",
    "value_error": "{error}",
    "string_type": "应为字符串",
    "int_type": "应为整数",
    "missing": "该字段为必填字段",
    "datetime_parsing": "无效的日期时间",
    "too_short": "该类型至少要有{min_length}个元素",
    "too_long": "该类型最多只能有{max_length}个元素",
    "greater_than_equal": "应大于或等于{ge}",
    "greater_than": "应大于{gt}",
    "less_than_equal": "应小于或等于{le}",
    "less_than": "应小于{lt}",
    "int_parsing": "无效的整数类型",
    "string_pattern_mismatch": "输入内容不符合正则匹配要求",
    "enum": "应为{expected}",
    "literal_error": "键名应为{expected}",
    "ip_v4_network": "输入的IP段存在错误",
    "json_invalid": "JSON解析错误",
    "list_type": "应为列表",
    "url_parsing": "输入内容应为http或https的绝对路径",
    "datetime_type": "应为时间日期类型",
}


class FastapiPydanticValidateErrorDataUtil:
    """fastapi的pydantic验证失败信息转换工具类"""

    @staticmethod
    def data_convert(
        exc: RequestValidationError, convert_dict: dict[str, str]
    ) -> RequestValidationErrorConvertedDataT:
        """对相关错误信息进行转换

        Args:
            exc (RequestValidationError): fastapi的验证失败错误实例
            convert_enum (Type[Enum]): 提供转换信息的枚举类

        Returns:
            RequestValidationErrorConvertedDataT: 转换后的数据
        """
        # 转换后的数据
        converted_data = {}
        for err in exc.errors():
            # 验证错误的参数名称和参数类型(query、path或body等)
            err_params_type, err_params_name = err["loc"][0], err["loc"][1]
            # 获取pydantic给出的错误类型和错误信息
            err_type = err.get("type")
            err_msg = err.get("msg")
            # 对枚举中有的错误类型的错误信息进行转换
            if err_type and err_type in convert_dict.keys():
                err_msg_template = convert_dict.get(err_type, err_msg)
                err_ctx = err.get("ctx")
                if err_msg_template is not None:
                    # 当存在自定义错误信息模板时
                    if err_ctx is not None:
                        try:
                            # 当存在错误上下文时, 进行变量替换
                            err_msg = err_msg_template.format(**err_ctx)
                        except KeyError:
                            # 如果变量替换过程中出错, 则还是使用原来的错误信息
                            pass
                    else:
                        # 当不存在错误上下文时, 直接使用错误信息模板作为错误信息
                        err_msg = err_msg_template
            converted_data[err_params_name] = {
                "err_type": err_params_type,
                "err_message": err_msg,
            }
        return converted_data
